﻿using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;

namespace PhysicalExamination5.WebApi.Utility.Swagger
{
    /// <summary>
    /// Swagger扩展
    /// </summary>
    public static class SwaggerExtension
    {
        /// <summary>
        /// 扩展方法 来一个独立的封装
        /// </summary>
        /// <param name="builder"></param>
        public static void AddSwaggerGenExt(this WebApplicationBuilder builder)
        {
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen(option =>
            {
                #region 组件支持版本展示
                //根据API版本信息生成API文档
                var provider = builder.Services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    option.SwaggerDoc(description.GroupName, new OpenApiInfo
                    {
                        Description = "PhysicalExamination5",
                        Title = "体检Api文档",
                        Version = description.ApiVersion.ToString()
                    });
                }


                //在Swagger 文档显示的API地址中将版本信息参数替换成实际的版本号
                option.DocInclusionPredicate((version, apiDescription) =>
                {
                    if (!version.Equals(apiDescription.GroupName))
                        return false;

                    IEnumerable<string>? values = apiDescription!.RelativePath.Split('/').Select(v => v.Replace("v{version}", apiDescription.GroupName));
                    apiDescription.RelativePath = string.Join("/", values);
                    return true;
                });

                //参数使用驼峰命名方式
                //option.DescribeAllParametersInCamelCase();
                //取消API文档需要输入版本信息
                //option.OperationFilter<RemoveVersionFromParameter>();
                #endregion


                #region 配置展示注释
                {
                    //xml文档绝对路径
                    var file = Path.Combine(AppContext.BaseDirectory, "PhysicalExamination5.WebApi.xml");
                    //true 显示控制器注释
                    option.IncludeXmlComments(file, true);
                    //对action的名称进行排序,如果有多个,就可以看见效果了
                    option.OrderActionsBy(o => o.RelativePath);
                }
                #endregion

                #region 扩展传入Token
                {
                    //添加安全定义
                    option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                    {
                        Description = "输入Token,格式为:Bearer xxxxxxxx（注意中间必须有空格）",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                        BearerFormat = "JWT",
                        Scheme = "Bearer"
                    });
                    //添加安全要求
                    option.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                                {
                                    new OpenApiSecurityScheme
                    {
                        Reference =new OpenApiReference()
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id ="Bearer"
                            }
                        },
                        new string[]{ }
                    }
                    });
                }
                #endregion

                //#region 扩展文件上传按钮
                //{
                //    option.OperationFilter<FileUploadFilter>();
                //}
                //#endregion

            });
        }


        /// <summary>
        /// Swagger中间件配置应用
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggerExt(this WebApplication app)
        {
            app.UseSwagger();
            //此代码就是验证引用:账户密码
            app.UseSwaggerAuthorized();
            app.UseSwaggerUI(options =>
            {
                #region 调用第三方程序包支持版本控制
                var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
                //默认加载最新版本的API文档
                foreach (var description in provider.ApiVersionDescriptions.Reverse())
                {
                    options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", $"体检Api {description.GroupName.ToUpperInvariant()}");
                }
                #endregion

            });
        }

    }
}
